package com.ziyueyuwen.xiniao.controller.file;

import com.suyeer.basic.util.HttpResUtil;
import com.suyeer.basic.util.LogUtil;
import com.suyeer.fastwechat.util.FwUtil;
import com.ziyueyuwen.xiniao.base.HttpResContent;
import com.ziyueyuwen.xiniao.enums.OssPathEnum;
import com.ziyueyuwen.xiniao.util.AudioUtil;
import com.ziyueyuwen.xiniao.util.OssUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.net.URL;

import static com.ziyueyuwen.xiniao.base.BaseUtil.*;
import static com.ziyueyuwen.xiniao.enums.OssPathEnum.*;
import static com.ziyueyuwen.xiniao.util.ConstUtil.*;

/**
 * @author jun 2018/12/19
 */
@Controller
@RequestMapping("/file")
public class FileController {

    @RequestMapping(value = "/upload_file.do", method = RequestMethod.POST)
    public void uploadFile(@RequestParam(PARAM_FILE) MultipartFile file,
                           @RequestParam(PARAM_FILE_TYPE) String fileType,
                           HttpServletRequest request,
                           HttpServletResponse response) {
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("上传文件");
        try {
            LogUtil.info("fileType: {}, fileName: {}, fileSize: {} KB, contentType: {}",
                    fileType, file.getOriginalFilename(), file.getSize() / 1000, file.getContentType());
            // check.
            checkParam(PARAM_FILE_TYPE, fileType);
            checkUploadFile(file);
            // do.
            String retUrl;
            String fileName = file.getOriginalFilename().toLowerCase();
            OssPathEnum ossPath = OssPathEnum.valueOf(fileType.toUpperCase());
            if (ossPath == TEST && fileName.endsWith(FILE_MP4_END_NAME)) {
                // 如果是学生作答的视频文件, 且文件是MP4类型, 则先返回url, 后台完成压缩并上传到oss
                String ossFileName = OssUtil.getUniqueFileName(fileName);
                retUrl = OssUtil.getOssFileUrl(ossFileName, ossPath);
                AudioUtil.handleAndroidMp4File(ossFileName, file, ossPath);
            } else {
                retUrl = OssUtil.putObjectToOss(file, ossPath, true);
            }
            if (StringUtils.isBlank(retUrl)) {
                throw new Exception("文件错误!");
            }
            saveSuccessMsgAndData(hrc, retUrl);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    /**
     * 单独处理上传的wav格式文件接口, 保存到系统后, 需要转码成MP3上传到oss, 然后返回oss地址
     *
     * @param file     MultipartFile
     * @param fileType String
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     */
    @RequestMapping(value = "/upload_wav_file.do", method = RequestMethod.POST)
    public void uploadWavFile(@RequestParam(PARAM_FILE) MultipartFile file,
                              @RequestParam(PARAM_FILE_TYPE) String fileType,
                              HttpServletRequest request,
                              HttpServletResponse response) {
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("上传 wav 文件");
        try {
            LogUtil.info("fileType: {}, fileName: {}, fileSize: {} KB, contentType: {}",
                    fileType, file.getOriginalFilename(), file.getSize() / 1000, file.getContentType());
            // check.
            checkParam(PARAM_FILE_TYPE, fileType);
            checkUploadFile(file);
            // do.
            OssPathEnum ossPath = OssPathEnum.valueOf(fileType.toUpperCase());
            String wavFileName = OssUtil.getUniqueFileName("test.wav");
            String mp3FileName = wavFileName.replace("wav", "mp3");
            String wavFilePath = AUDIO_FILE_PATH + wavFileName;
            String mp3FilePath = AUDIO_FILE_PATH + mp3FileName;
            FileUtils.copyToFile(file.getInputStream(), new File(wavFilePath));
            AudioUtil.wav2mp3(wavFilePath, mp3FilePath);
            Thread.sleep(500);
            String retUrl = OssUtil.putObjectToOss(new File(mp3FilePath), ossPath);
            Thread.sleep(100);
            AudioUtil.deleteFile(mp3FileName);
            AudioUtil.deleteFile(wavFileName);
            if (StringUtils.isBlank(retUrl)) {
                throw new Exception("文件错误!");
            }
            saveSuccessMsgAndData(hrc, retUrl);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    /**
     * 通过微信上传的音频时amr, 需要转码成mp3
     *
     * @param mediaId  String
     * @param fileType String
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     */
    @RequestMapping(value = "/get_file_url.do", method = RequestMethod.POST)
    public void getFileUrl(@RequestParam(PARAM_MEDIA_ID) String mediaId,
                           @RequestParam(PARAM_FILE_TYPE) String fileType,
                           HttpServletRequest request,
                           HttpServletResponse response) {
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("获取文件的url");
        try {
            // check.
            checkParam(PARAM_MEDIA_ID, mediaId);
            checkParam(PARAM_FILE_TYPE, fileType);
            // do.
            OssPathEnum ossPath = OssPathEnum.valueOf(fileType.toUpperCase());
            String retUrl = null;
            if (ossPath == STUDENT_ANSWER_WX_AUDIO) {
                String mp3FileName = OssUtil.getUniqueFileName("test.mp3");
                retUrl = OssUtil.getOssFileUrl(mp3FileName, ossPath);
                uploadAudio(mediaId, mp3FileName);
            }
            if (ossPath == STUDENT_ANSWER_WX_IMG) {
                retUrl = uploadImg(mediaId);
            }
            if (StringUtils.isBlank(retUrl)) {
                throw new Exception("文件错误!");
            }
            saveSuccessMsgAndData(hrc, retUrl);
        } catch (Exception e) {
            saveErrorMsgAndData(hrc, e);
        } finally {
            HttpResUtil.writeResult(hrc, true);
        }
    }

    private String uploadImg(String mediaId) throws Exception {
        String wxFileUrl = String.format(WX_GET_MEDIA_FILE, FwUtil.getAccessToken(), mediaId);
        URL url = new URL(wxFileUrl);
        String contentType = url.openConnection().getContentType();
        String fileName = null;
        if ("image/jpeg".equalsIgnoreCase(contentType)) {
            fileName = "test.jpg";
        }
        if ("image/png".equalsIgnoreCase(contentType)) {
            fileName = "test.png";
        }
        if ("image/gif".equalsIgnoreCase(contentType)) {
            fileName = "test.gif";
        }
        if (StringUtils.isBlank(fileName)) {
            throw new Exception("暂不支持当前文件类型: " + contentType);
        }
        fileName = OssUtil.getUniqueFileName(fileName);
        return OssUtil.putObjectToOss(url.openStream(), fileName, STUDENT_ANSWER_WX_IMG);
    }

    private void uploadAudio(String mediaId, String mp3FileName) throws Exception {
        try {
            String wavFileName = mp3FileName.replace("mp3", "wav");
            String spxFileName = mp3FileName.replace("mp3", "speex");

            String wavFilePath = AUDIO_FILE_PATH + wavFileName;
            String mp3FilePath = AUDIO_FILE_PATH + mp3FileName;
            String spxFilePath = AUDIO_FILE_PATH + spxFileName;

            String wxFileUrl = String.format(WX_GET_SPEEX_MEDIA_FILE, FwUtil.getAccessToken(), mediaId);
            URL spxUrl = new URL(wxFileUrl);
            File spxFile = new File(spxFilePath);
            FileUtils.copyURLToFile(spxUrl, spxFile);
            Thread.sleep(100);
            AudioUtil.spx2wav(spxFilePath, wavFilePath);
            Thread.sleep(100);
            AudioUtil.wav2mp3(wavFilePath, mp3FilePath);
            Thread.sleep(100);
            File mp3File = new File(mp3FilePath);
            OssUtil.putObjectToOss(mp3File, STUDENT_ANSWER_WX_AUDIO);
            Thread.sleep(100);
            AudioUtil.deleteFile(mp3FileName);
            AudioUtil.deleteFile(spxFileName);
            AudioUtil.deleteFile(wavFileName);
        } catch (Exception e) {
            LogUtil.error(e);
            throw new Exception("下载录音录音转码失败!");
        }
    }

    private void checkUploadFile(MultipartFile multipartFile) throws Exception {
        if (multipartFile == null || multipartFile.getInputStream() == null) {
            throw new IllegalArgumentException("上传文件为空");
        }
        if (multipartFile.getSize() > FILE_MAX_SIZE_ALLOWED * FILE_SIZE_1_M) {
            throw new IllegalArgumentException(String.format("文件太大，最大不能超过%dM", FILE_MAX_SIZE_ALLOWED));
        }
    }

}
